{ "cells": [ { "cell_type": "markdown", "metadata": { "toc": "true" }, "source": [ "

Table of Contents

\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Issue 11" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from persist.archive import Archive\n", "x = [1, 2, 3]\n", "y = [x, x]\n", "a = Archive(scoped=False)\n", "a.insert(y=y)\n", "s = str(a)\n", "d = {}\n", "exec(s, d)\n", "y_ = d['y']\n", "assert y[0] is y[1]\n", "assert y_[0] is y_[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After a bit of inspection, I found that the problem occurs at the reduction state. The call to `Graph.reduce()` is a bit too eager. Need to find out why. (Found a few bugs in the constructors for `Graph` and `Graph_` which should be similar...)\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": "20%" } }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": { "image/png": { "width": "20%" } }, "output_type": "display_data" } ], "source": [ "from IPython.display import Image, display\n", "import os\n", "import sys\n", "import trace\n", "\n", "from persist.archive import Archive\n", "x = [1, 2, 3]\n", "y = [x, x]\n", "\n", "from pycallgraph2 import PyCallGraph\n", "from pycallgraph2.output import GraphvizOutput\n", "\n", "images = []\n", "\n", "a = Archive(scoped=True)\n", "a.insert(y=y)\n", "with PyCallGraph(output=GraphvizOutput()):\n", " s = str(a)\n", "images.append(Image(filename='pycallgraph.png', width=\"20%\"))\n", "os.remove('pycallgraph.png')\n", "\n", "a = Archive(scoped=False)\n", "a.insert(y=y)\n", "with PyCallGraph(output=GraphvizOutput()):\n", " s = str(a)\n", "images.append(Image(filename='pycallgraph.png', width=\"20%\")) \n", "os.remove('pycallgraph.png')\n", "\n", "display(*images)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'Archive' object has no attribute '_graph'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnodes\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mAttributeError\u001b[0m: 'Archive' object has no attribute '_graph'" ] } ], "source": [ "g = a._graph\n", "g.nodes" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# create a Trace object, telling it what to ignore, and whether to\n", "# do tracing or line-counting or both.\n", "tracer = trace.Trace(\n", " ignoredirs=[sys.prefix, sys.exec_prefix],\n", " trace=1,\n", " count=1)\n", "\n", "# run the new command using the given tracer\n", "tracer.run('str(a)')\n", "\n", "# make a report, placing output in the current directory\n", "r = tracer.results()\n", "#r.write_results(show_missing=True, coverdir=\".\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The question here is who is responsible for ensuring that objects are not duplicated?\n", "* The method `get_persistent_rep_list()` uses two names... so not here (but still has the same object).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Import Issues" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The objective is to prevent the data from being loaded until `import ds.x` is called. This allows multiple processes to work with data independently with a lock file being required only when changing the metadata in `_info_dict`. To implement this we use the following trick suggested by [Alex Martelli](https://en.wikipedia.org/wiki/Alex_Martelli):\n", "\n", " * [Can modules have properties the same way that objects can?](https://stackoverflow.com/a/880550/1088938)\n", "\n", "Such a module might look like this:\n", " \n", "```python\n", "import sys\n", "import numpy as np\n", "sys.modules[__name__] = np.array([0, 1, 2, 3])\n", "```\n", " \n", "or like this (if loaded from disk):\n", " \n", "```python\n", "import os.path\n", "import sys\n", "import numpy as np\n", "datafile = os.path.splitext(__file__)[0] + \"_data.npy\"\n", "sys.modules[__name__] = np.load(datafile)\n", "```\n", "\n", "This seems to work very nicely. The imported array appears as part of the top-level module no matter how it is imported, and is only loaded when explicitly requested." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Byte Compiling" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is very subtle issue with using the import mechanism for DataSets. When updating an attribute of a DataSet, we change the corresponding `.py` file on disk. However, if this change is made too quickly after importing the attribute, it is possible that the byte-compiled `.pyc` file might not be finished compiling until *after* the `.py` file is updated. In this case, the `.py` file will have an earlier timestamp than the `.pyc` file and so python will incorrectly assume that the `.pyc` file is authoritative.\n", "\n", "I do not see a good solution yet, so for now we use [`sys.dont_write_bytecode`](https://docs.python.org/2/library/sys.html?highlight=bytecode#sys.dont_write_bytecode):\n", "\n", "* https://stackoverflow.com/a/154617" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Reloading" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Reloading data can also be an issue when replacing modules. For example, if we have a module `mod` and array `d` that is replaced, then what should `reload(mod)` do if `d` is updated on disk.\n", "\n", "Our solution is the following:\n", "\n", "* Delete all attributes like `mod.d` upon reload so that the user needs to re-import `mod.d` etc. This is done in the `__init__.py` file.\n", "* This behaviour is inconstant with the normal python import machinery, so we only do it for objects that were specified with `single_item_mode`. The reason we do it here is that the user cannot `reload(mod.d)` since this is an array. If the user does not want this behaviour, then they can disable `single_item_mode`.\n", "* The alternative behaviour might be to reload all data that has already been imported. We might provide a flag for this later if requested." ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python [conda env:work]", "language": "python", "name": "conda-env-work-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" }, "toc": { "base_numbering": 1, "nav_menu": { "height": "30px", "width": "252px" }, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": {}, "toc_section_display": "block", "toc_window_display": true }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }